using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace WindowsUserControl.UIUpdateWrapper
{
    /// <summary>
    /// 
    /// </summary>
    public class TreeViewUpdator
    {
        private TreeView _TreeView;
        private Dictionary<string,TreeNode> _TreeNodesByNodeString;
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="htnodes"></param>
        public TreeViewUpdator(TreeView tv, Dictionary<string,TreeNode> htnodes)
        {
            this._TreeView = tv;
            this._TreeNodesByNodeString=new Dictionary<string, TreeNode>();

            foreach (string key in htnodes.Keys)
            {
                string nodePath = this.TidyNodePath(key.ToString());
                this._TreeNodesByNodeString.Add(nodePath, htnodes[key]);
            }
            this._TreeView.Invoke(new MethodInvoker(this.BindTreeNodes));
        }

        private void BindTreeNodes()
        {
            this._TreeView.Nodes.Clear();
            if (this._TreeNodesByNodeString != null && this._TreeNodesByNodeString.Count > 0)
            {
                string[] nodePaths = new string[this._TreeNodesByNodeString.Count];
                this._TreeNodesByNodeString.Keys.CopyTo(nodePaths, 0);
                nodePaths = this.SortTreeNodePaths(nodePaths);
                Dictionary<string, TreeNode> htMyNodes = new Dictionary<string, TreeNode>();
                for(int i=0;i<nodePaths.Length;i++)
                {
                    string nodePath = nodePaths[i];
                    if(nodePath.Length==1)
                        nodePath = "000" + nodePath;
                    else if(nodePath.Length==2)
                        nodePath = "00" + nodePath;
                    else if(nodePath.Length==3)
                        nodePath = "0" + nodePath;

                    TreeNode tn = this._TreeNodesByNodeString[nodePath];
                    if(tn!=null)
                    {
                        TreeNode cloneTn = this.CloneTreeNode(tn);
                        string[] nodeIndexes = nodePath.Split(new char[] {'.'});
                        if(nodeIndexes.Length>1)
                        {
                            string parentNodePath = nodePath.Substring(0, nodePath.LastIndexOf("."));
                            TreeNode parentTn = htMyNodes[parentNodePath] as TreeNode;
                            if(parentTn !=null)
                            {
                                parentTn.Nodes.Add(cloneTn);
                            }
                            else
                            {
                                this._TreeView.Nodes.Add(cloneTn);
                            }
                        }
                        else
                        {
                            this._TreeView.Nodes.Add(cloneTn);
                        }

                        htMyNodes.Add(nodePath,cloneTn);
                    }
                }
                this._TreeNodesByNodeString = htMyNodes;
            }

            this._TreeView.SelectedNode = null;
            this._TreeView.ExpandAll();
            this._TreeView.Refresh();
        }

        private string[] SortTreeNodePaths(string[] nodePaths)
        {
            List<string> nodePathList=new List<string>();
            if(nodePaths !=null && nodePaths.Length>0)
            {
                for(int i=0;i<nodePaths.Length;i++)
                {
                    string tidyPath = this.TidyNodePath(nodePaths[i]);
                    if (tidyPath.Trim().Length > 0)
                    {
                        nodePathList.Add(tidyPath);
                    }
                }
            }
            nodePathList.Sort();
            return nodePathList.ToArray();
        }

        private string TidyNodePath(string nodePath)
        {
            string[] nodeNames = nodePath.Split(new char[] {'.'});
            string tidyPath = string.Empty;
            for(int i=0;i<nodeNames.Length;i++)
            {
                string name = nodeNames[i];
                if(name.Length==1)
                    name = "000" + name;
                else if(name.Length==2)
                    name = "00" + name;
                else if(name.Length==3)
                    name = "0" + name;

                tidyPath += name;

                if (i < nodeNames.Length - 1)
                    tidyPath += ".";
            }
            return tidyPath;
        }

        private TreeNode CloneTreeNode(TreeNode tn)
        {
            TreeNode clone= new TreeNode(tn.Text,tn.ImageIndex,tn.SelectedImageIndex);
            clone.Tag = tn.Tag;
            return clone;
        }
    }
}
